package com.yang.modules.common.lock.impl;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.yang.modules.common.lock.LockClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;

/**
 * @author Billyang
 * @date 2024/8/5 16:08
 */
@Primary
@Component
@Slf4j
public class JvmLockClient implements LockClient {

    private Cache<String, ReentrantLock> locks = CacheBuilder.newBuilder()
            .maximumSize(10000)
            .expireAfterAccess(10, TimeUnit.SECONDS)
            .removalListener(listener -> {
                log.info("key:{},value:{},cause:{}", listener.getKey(), listener.getValue(), listener.getCause());
            }).build();

    @Override
    public <V> V doInLock(String name, Supplier<V> supplier) {
        ReentrantLock lock = getLock(name);
        try {
            lock.lock();
            return supplier.get();
        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    private ReentrantLock getLock(String name) {
        try {
            return locks.get(name, () -> new ReentrantLock());
        } catch (Exception e) {
            log.error("getLock error", e);
        }
        return new ReentrantLock();
    }
}
